"""
Case Type   : 操作系统类-文件系统故障
Case Name   : 备机build时 注入故障文件系统句柄耗尽
Create At   : 2021/7/19
Owner       : @wan005
Description :
    1、备节点上执行gs_ctl build
    2、备节点注入文件句柄耗尽故障
    3、清理故障，
    4、再次build
    5、执行TPCC
    6、检查数据一致性
    7、恢复环境
Expect      :
    1、build失败
    2、故障注入成功
    3、清理故障成功
    4、build成功
    5、执行TPCC成功
    6、数据一致
    7、恢复环境
History     :
    Modified by @wan005 2021/8/23: 优化故障清理
    Modified by @wan005 2021/12/9: 优化故障清理后重启数据库
"""
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.sta_1_sh = CommonSH(self.nodes[1])
        self.sta_2_sh = CommonSH(self.nodes[2])
        self.primary_root_node = Node(node="PrimaryRoot")
        self.sta1_root_node = Node(node="Standby1Root")
        self.sta1_node = Node(node="Standby1DbUser")
        self.constant = Constant()
        self.com = Common()
        self.log.info("setUp-实例化:ok")

        self.log.info("Opengauss_Reliability_OS_File_System_Case018:开始执行")
        self.inject_cmd = f"rfile_deplenish (timeout) values (120)"

    def test_main(self):
        try:
            self.log.info("步骤1:备节点上执行gs_ctl build")
            session1 = ComThread(self.sta_1_sh.executeGsctl,
                                 args=("build",
                                       "server started",
                                       "-b full",
                                       True,))
            session1.setDaemon(True)
            session1.start()
            time.sleep(1)

            self.log.info("步骤2:备节点注入句柄耗尽故障")
            self.log.info("注入故障")
            session2 = ComThread(self.com.cfe_inject,
                                 args=(self.sta1_root_node,
                                       self.inject_cmd))
            session2.setDaemon(True)
            session2.start()

            session2.join(60)
            result = session2.get_result()
            self.log.info(result)
            self.assertIn("successful execution", result)

            self.log.info("gs_ctl build结果")
            session1.join(120)
            session1_result = session1.get_result()
            self.log.info("result start------------------")
            self.log.info(session1_result)
            self.log.info("result over-------------------")
            self.assertIn("failed", session1_result)
            self.assertNotIn("server started", session1_result)

        finally:
            self.log.info("步骤3:清除故障")
            time.sleep(120)
            result = self.primary_sh.stopDbCluster(get_detail=True)
            self.log.info(result)

            result = self.primary_sh.startDbCluster(get_detail=True)
            self.log.info(result)

        self.log.info("步骤4:故障清理后，备节点上再次执行gs_ctl build")
        result = self.sta_1_sh.executeGsctl("build",
                                            "server started",
                                            param="-b full",
                                            get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result)
        self.assertNotIn("Too many open files", result)

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status or "Normal" in db_status)

        self.log.info("步骤5:运行TPCC")
        result = self.com.startTPCC(self.primary_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result)

        self.log.info('检查主备是否同步')
        time.sleep(10)
        self.log.info('获取节点数量')
        node_num = self.primary_sh.get_node_num()
        res = self.primary_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res)

        self.log.info('步骤6:检查数据一致性')
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag)
        table_dict = self.com.format_sql_result(
            self.primary_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f'select count(*) from {name};'
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag)

    def tearDown(self):
        self.log.info("步骤7:环境清理")
        time.sleep(120)
        self.log.info("故障已清理")
        result = self.primary_sh.stopDbCluster(get_detail=True)
        self.log.info(result)

        result = self.primary_sh.startDbCluster(get_detail=True)
        self.log.info(result)

        result = self.primary_sh.check_whether_need_build()
        success_msg = self.constant.BUILD_SUCCESS_MSG
        if result:
            result = self.sta_1_sh.executeGsctl('build',
                                                success_msg,
                                                '-b full')
            self.assertTrue(result)
            result = self.sta_2_sh.executeGsctl('build',
                                                success_msg,
                                                '-b full')
            self.assertTrue(result)

        result = Node(self.nodes[1]).sh("date").result()
        self.assertNotIn("Too many open files", result)
        self.log.info("Opengauss_Reliability_OS_File_System_Case018:执行完成")
